package cn.bellychang.bobo.linkedlist;

import cn.bellychang.bobo.arraylist.Iterator;

/**
 * @author ChangLiang
 * @date 2020/9/11
 */
public class TwoWayLinkedList<E> {

    /**
     * 第一个node
     */
    private Node head;

    /**
     * 最后一个node
     */
    private Node tail;

    private int size;

    public TwoWayLinkedList() {
        Node dummyNode = new Node();
        head = tail = dummyNode;
    }

    public int getSize() {
        return this.size;
    }

    public void addLast(E e) {
        Node newNode = new Node();
        newNode.value = e;
        newNode.prev = tail;
        tail.next = newNode;
        tail = newNode;
        if (size == 0) {
            head = newNode;
        }
        size++;
    }

    public void addFirst(E e) {
        Node newNode = new Node();
        newNode.value = e;
        newNode.next = head;
        head.prev = newNode;
        head = newNode;
        if (size == 0) {
            tail = newNode;
        }
        size++;
    }

    private void checkIsEmpty() {
        if (size == 0) {
            throw new RuntimeException("linked list is emypty");
        }
    }

    public E getFirst() {
        checkIsEmpty();
        return head.value;
    }

    public E getLast() {
        checkIsEmpty();
        return tail.value;
    }

    public E removeFirst() {
        checkIsEmpty();
        Node temp = head;
        head = head.next;
        size--;
        return temp.value;
    }

    public E removeLast() {
        checkIsEmpty();
        Node temp = tail;
        tail = tail.prev;
        size--;
        return temp.value;
    }

    public Iterator<E> iterator() {
        return new Iterator<E>() {

            Node temp = head;

            int count = 0;

            @Override
            public boolean hasNext() {
                return count < size;
            }

            @Override
            public E next() {
                Node result = temp;
                count++;
                temp = temp.next;
                return result.value;
            }
        };
    }

    class Node {
        private Node prev;

        private Node next;

        private E value;
    }
}
